﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Logs.Core;

namespace Pixysoft.Framework.Logs.Controller
{
    class LogReportController
    {
        private static volatile LogReportController instance;

        private static object syncRoot = new Object();

        public static LogReportController Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        instance = new LogReportController();
                    }
                }

                return instance;

            }
        }


        public ILogReport ParseReport(string fullfilename)
        {
            string path = StringFilter.GetFilePath(fullfilename);
            fullfilename = StringFilter.GetFileName(fullfilename);
            ILogCommand command = new LogCommand(path, fullfilename);
            command.CrossFiles = false;
            command.Level = LogLevel.ALL;
            command.Module = null;
            ILogDocument doc = command.ExecuteReader();

            DateTime now = Pixysoft.Tools.GlobalTimer.Instance.GetGlobalTime();

            LogReport report = new LogReport();

            report.Id = "N/A (parse format)";

            report.Record = null;

            report.TimeSpan = -1;

            report.TimeFrom = now;

            report.TimeTo = now;

            report.Document = doc;

            return report;

        }

        public ILogReport ParseRecentReport(ILoggerSetting setting, int millisec, LogLevel level)
        {
            DateTime now = Pixysoft.Tools.GlobalTimer.Instance.GetGlobalTime();

            LogReport report = new LogReport();

            report.Id = "N/A (recent format)";

            report.Record = null;

            report.TimeSpan = millisec;

            report.TimeFrom = now.AddMilliseconds(-1 * millisec);

            report.TimeTo = now;

            report.Document = GetDocument(setting, report.TimeFrom, report.TimeTo, level);

            return report;
        }

        /// <summary>
        /// 搜索指定id附近的日志
        /// </summary>
        /// <param name="coreLogger"></param>
        /// <param name="id"></param>
        /// <param name="millisec"></param>
        /// <returns></returns>
        public ILogReport GetReport(ILoggerSetting setting, string id, int millisec)
        {
            LogReport report = new LogReport();

            report.Id = id;

            report.TimeSpan = millisec;

            ILogRecord record = GetRecord(setting, id, true);

            if (record == null)
                return report;

            report.Record = record;

            report.TimeFrom = record.Date.AddMilliseconds(-1 * millisec);

            report.TimeTo = record.Date.AddMilliseconds(millisec);

            report.Document = GetDocument(setting, report.TimeFrom, report.TimeTo, LogLevel.ALL);

            report.FrameDocuments = GetFrameDocuments(record, millisec);

            return report;
        }

        public ILogRecord GetRecord(ILoggerSetting setting, string id, bool crossfiles)
        {
            LogIdCommand command = new LogIdCommand(setting.GetLogFilePath(), setting.Filename + StringHelper.default_log_postfix, id, crossfiles);

            return command.ExecuteReader();
        }

        private ILogDocument GetDocument(ILoggerSetting setting, DateTime from, DateTime to, LogLevel level)
        {
            ILogCommand command = new LogCommand(setting.GetLogFilePath(), setting.Filename + StringHelper.default_log_postfix);

            command.CrossFiles = true;

            command.Range.From = from;

            command.Range.To = to;

            command.Level = level;

            command.Module = setting.Modulename;

            return command.ExecuteReader();
        }

        private ILogDocument[] GetFrameDocuments(ILogRecord record, int millisec)
        {
            List<ILogDocument> list = new List<ILogDocument>();

            foreach (ILogFrame frame in record.Frames)
            {
                string dll = frame.Dll;

                if (string.IsNullOrEmpty(dll))
                    continue;

                LogDirectoryStruct strut = LogRegisterController.Instance.GetRegisterFilepath(dll);

                if (strut == null)
                    continue;

                if (record.Filepath.Equals(strut.Filepath + strut.Filename + StringHelper.default_log_postfix, StringComparison.OrdinalIgnoreCase))
                    continue;

                ILogCommand command = new LogCommand(strut.Filepath, strut.Filename + StringHelper.default_log_postfix);

                command.CrossFiles = true;

                command.Range.From = record.Date.AddMilliseconds(-1 * millisec);

                command.Range.To = record.Date.AddMilliseconds(millisec);

                command.Level = LogLevel.ALL;

                ILogDocument doc = command.ExecuteReader();

                if (doc == null)
                    continue;

                list.Add(doc);
            }

            return list.ToArray();
        }
    }
}
